<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例的原生实现</title>
</head>
<body>
<script>

    // 对象没有作用域，所以 this 没有意义
    // let person = {
    //     firstName: 'Kris',
    //     lastName: 'Wu'
    // };

    // JavaScript中给对象添加函数的方式
    // person.fullName = function assemble() {
    //     this.fullName = this.firstName + '-' + this.lastName; // 没有意义
    //     return this.firstName + '-' + this.lastName;
    // };

    // 加()才可以，不加直接打印函数
    // console.log(person.fullName());

    /*
     * 不使用框架进行编码时，什么时候用 defineProperty ?
     *  1. 要追加的属性来自于其他属性的加工(计算)
     *  2. 对属性的读/写有权限控制的需求
     *  3. 需要监听属性的读/写时
     */
    let stardust = {
        firstName: 'star',
        lastName: 'dust'
    };

    /*
     * Invalid property descriptor. Cannot both specify accessors and a value or writable
     * 这个错误是因为：Object.defineProperty(object, propertyName, descriptor) 定义新属性时
     * descriptor 中同时有 访问器(getter/setter) 与 value/writable 属性
     */
    Object.defineProperty(stardust, "fullName", {
        // 能否使用 delete、能否需改属性特性、或能否修改访问器属性、false 为不可重新定义，默认值为 true
        configurable: true,
        // 对象属性是否可通过 for-in 循环，false 为不可循环，默认值为true
        enumerable: true,
        // 对象属性是否可修改,false 为不可修改，默认值为true
        // writable:false,
        // 对象属性的默认值，默认值为 undefined
        // value: undefined,
        // 调用时机：读取 fullName 时调用，get 中的 this 是 stardust
        get(){
            return this.firstName + '-' + this.lastName;
        },
        // 调用时机：直接修改 fullName 时调用，set 中的 this 是 stardust，set 可以接收预修改的值
        set(value){
            // 为什么可以避免递归 ?
            // 想明白了，因为这个 const fullName = value; 根本没用！哈哈哈，想不到吧？后面的代码给 firstName 和 lastName 都赋值了
            // 在取 fullName 的时候，是通过 get() 函数取的 firstName 和 laseName，并不是取的 fullName 本身的值
            // 所以，const fullName = value; 根本没用。
            // const fullName = value;
            // 跟上面那行代码一样没用
            // const test = "hello world";
            // 这行有意义但纯属脱裤子放屁
            // const name = fullName.split('-');

            // 真正起作用的是下面的代码
            // const name = value.split('-');
            // this.firstName = name[0];
            // this.lastName = name[1];
        }
    });

    console.log(stardust.fullName);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 1.
    // function Stardust(){
    //     // this.name;
    // }
    //
    // let stardust = new Stardust();
    //
    // function feature(){
    //     window.alert("新坠星尘");
    // }
    //
    // stardust.name = feature;
    // stardust.name();

    // 2.
    // function Stardust() {
    //     this.name = "xx";
    // }
    //
    // let stardust = new Stardust();
    //
    // stardust.name = function show1() {
    //     window.alert("新坠星尘");
    // };
    //
    // stardust.name();

    // 3. 原型法（多个对象可共享函数）
    // function Stardust() {
    // }
    //
    // let stardust = new Stardust();
    //
    // Stardust.prototype.shout = function () {
    //     window.alert("新坠星尘");
    // };
    // stardust.shout();
    //
    // let stardust2 = new Stardust();
    // stardust2.shout();

    // 4. 使用传入的实参初始化属性
    // function Stardust(name, age){
    //     this.name = name;
    //     this.age = age;
    // }
    //
    // window.show = function () {
    //     window.alert("新坠星尘");
    // };
    //
    // let stardust = new Stardust(this.show, 21);
    //
    // stardust.name();
</script>
</body>
</html>
